package com.why.simpleboot.core.core;

import com.why.simpleboot.core.annotation.aop.Import;
import com.why.simpleboot.core.core.factory.*;
import com.why.simpleboot.core.extend.SimpleBootApplicationRunner;
import com.why.simpleboot.core.common.utils.SimpleReflectUtils;

import com.why.simpleboot.core.extend.ImportAfterBeanRegistrar;
import com.why.simpleboot.core.extend.ImportBeforeBeanRegistrar;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Set;

/**
 * @program: why-simpleboot-framework
 * @description: 容器上下文的初始化
 * @author: @why
 * @create: 2021-05-22 17:30
 **/
public class ApplicationContext implements Factory {
    private final ClassFactory CLASS_FACTORY = new ClassFactory();

    private final RouterFactory ROUTER_FACTORY = new RouterFactory();

    private final InterceptorFactory INTERCEPTOR_FACTORY = new InterceptorFactory();

    private final BeanFactory BEAN_FACTORY = new BeanFactory(INTERCEPTOR_FACTORY);

    private static final ApplicationContext ANNOTATION_APPLICATION_CONTEXT = new ApplicationContext();

    private final ScheduleFactory SCHEDULE_FACTORY = new ScheduleFactory();

    private ApplicationContext() {

    }

    public void init(List<String> basePackagesList, Class<?> mainClass) {

        String[] basePackages = basePackagesList.toArray(new String[0]);
//       加载Class对象
        CLASS_FACTORY.loadClasses(basePackages);
//        加载前置处理器 ---> 扩展点，继承 ImportBeforeBeanRegistrar 接口的类会被执行
        processAllBeforeRegistrar(mainClass, basePackagesList);
//            处理controller,处理url 对应的 方法
        ROUTER_FACTORY.loadRouters(CLASS_FACTORY.getCLASSES());
//            加载所有的拦截器  (AOP)
        INTERCEPTOR_FACTORY.LoadInterceptors(CLASS_FACTORY.getCLASSES(), basePackages);
//            完成bean的装配  依赖注入   AOP代理类的生成
        BEAN_FACTORY.loadBeans(CLASS_FACTORY.getCLASSES(), basePackages);
//        加载后置处理方法
        processAllAfterRegistrar(mainClass, basePackagesList);

    }


    /**
     * 执行应用运行后的扩展点
     *
     * @param basePackages
     */
    public void startRunner(String... basePackages) {
        Set<Class<? extends SimpleBootApplicationRunner>> ApplicationRunner = SimpleReflectUtils.getSubclass(SimpleBootApplicationRunner.class, basePackages);
        for (Class<? extends SimpleBootApplicationRunner> runner : ApplicationRunner) {
            SimpleBootApplicationRunner runnerAble = (SimpleBootApplicationRunner) SimpleReflectUtils.getInstance(runner);
            runnerAble.run(this);
        }
        clearCache();
    }

    public Object getBean(String name) {
        return BEAN_FACTORY.getBEANS().get(name);
    }


    /**
     * 处理所有的ImportBeforeBeanRegistrar
     *
     * @see ImportBeforeBeanRegistrar
     */
    private void processAllBeforeRegistrar(Class<?> mainClass, List<String> basePackagesList) {
        //拿到主启动类
        Annotation[] annotations = mainClass.getAnnotations();
        for (Annotation annotation : annotations) {
            Import anImport = (Import) SimpleReflectUtils.getTargetAnnotation(annotation.annotationType(), Import.class);
            if (anImport != null) {
                Class<?>[] classes = anImport.clazz();
                if (classes != null && classes.length > 0) {
                    for (Class<?> aClass : classes) {
                        /*
                        父类.class.isAssignableFrom(子类.class)
                         */
                        if (ImportBeforeBeanRegistrar.class.isAssignableFrom(aClass)) {
                            ImportBeforeBeanRegistrar registrar = (ImportBeforeBeanRegistrar) SimpleReflectUtils.getInstance(aClass);
                            registrar.registerBeans(this, basePackagesList, mainClass);
                        }
                    }
                }
            }

        }
    }


    /**
     * 处理所有的ImportAfterBeanRegistrar
     *
     * @see ImportAfterBeanRegistrar
     */
    public void processAllAfterRegistrar(Class<?> clazz, List<String> basePackagesList) {
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {

            Import anImport = (Import) SimpleReflectUtils.getTargetAnnotation(annotation.annotationType(), Import.class);

            if (anImport != null) {
                Class<?>[] classes = anImport.clazz();
                if (classes != null && classes.length > 0) {
                    for (Class<?> aClass : classes) {
                        if (ImportAfterBeanRegistrar.class.isAssignableFrom(aClass)) {
                            ImportAfterBeanRegistrar registrar = (ImportAfterBeanRegistrar) SimpleReflectUtils.getInstance(aClass);
                            registrar.registerBeans(this, basePackagesList, clazz);
                        }


                    }
                }
            }

        }

    }


    /**
     * 清空无用缓存
     */
    public void clearCache() {
        CLASS_FACTORY.getCLASSES().clear();
    }

    public static ApplicationContext getAnnotationApplicationContext() {
        return ANNOTATION_APPLICATION_CONTEXT;
    }

    public ClassFactory getClassFactory() {
        return CLASS_FACTORY;
    }

    public RouterFactory getRouterFactory() {
        return ROUTER_FACTORY;
    }

    public InterceptorFactory getInterceptorFactory() {
        return INTERCEPTOR_FACTORY;
    }

    public BeanFactory getBeanFactory() {
        return BEAN_FACTORY;
    }

    public ScheduleFactory getScheduleFactory() {
        return SCHEDULE_FACTORY;
    }
}
